package com.legolas.thread;

import java.util.Random;
import java.util.concurrent.*;

/**
 * Created with IntelliJ IDEA.
 * User: Legolas
 * Date: 2017/10/24 0024
 */
public class ThreadCommunication {

    public static void main(String args[]) {
        //demo1();
        // demo2();
        //demo3();
        //runDAfterABC();
        //runABCWhenAllReady();
        doTaskWithResultInWorker();
    }

    //A B同时执行
    private static void demo1() {
        Thread A = new Thread(() -> printName("A"));
        Thread B = new Thread(() -> printName("B"));
        A.start();
        B.start();
    }

    //A先执行完B执行
    private static void demo2() {
        Thread A = new Thread(() -> printName("A"));
        Thread B = new Thread(() -> {
            System.out.println("B开始等待A");
            try {
                A.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            printName("B");
        });
        A.start();
        B.start();
    }

    //synchronized关键字指定线程执行顺序
    private static void demo3() {
        //创建A和B共享的对象锁
        Object lock = new Object();
        Thread A = new Thread(() -> {
            synchronized (lock) {//A得到锁
                System.out.println("A 1");
                try {
                    lock.wait();//A释放控制权进入wait状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("A 2");
                System.out.println("A 3");
            }
        });

        Thread B = new Thread(() -> {
            synchronized (lock) {//B得到锁
                System.out.println("B 1");
                System.out.println("B 2");
                System.out.println("B 3");
                lock.notify();//B释放锁，唤醒了正在wait的A
            }
        });
        A.start();
        B.start();
    }

    //四个线程 A B C D，其中 D 要等到 A B C 全执行完毕后才执行，而且 A B C 是同步运行的
    public static void runDAfterABC() {
        int worker = 3;
        //CountDownLatch是一个倒数计数器
        CountDownLatch countDownLatch = new CountDownLatch(worker);
        new Thread(() -> {
            System.out.println("D is waiting for other three threads");
            try {
                countDownLatch.await();//检查计数器值是否为0，若不为0继续保持等待状态
                System.out.println("All done,D starts working");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        for (char threadName = 'A'; threadName <= 'C'; threadName++) {
            final String tN = String.valueOf(threadName);
            new Thread(() -> {
                System.out.println(tN + " is working");
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(tN + " is finished");
                countDownLatch.countDown();//每次将倒计数减一
                System.out.println(countDownLatch.getCount());
            }).start();

        }
    }

    //线程 A B C 各自开始准备，直到三者都准备完毕，然后再同时运行
    //在runDAfterABC中CountDownLatch计时结束只有一个await()会得到响应
    private static void runABCWhenAllReady() {
        int runner = 3;
        //设置3个线程数同时等待
        CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);
        final Random random = new Random();
        for (char runnerName = 'A'; runnerName <= 'C'; runnerName++) {
            final String tN = String.valueOf(runnerName);
            new Thread(() -> {
                long prepareTime = random.nextInt(10000) + 100;
                System.out.println(tN + " is preparing for time:" + prepareTime);
                try {
                    Thread.sleep(prepareTime);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                try {
                    System.out.println(tN + " is prepared ,waiting for others");
                    cyclicBarrier.await();//当前线程准备完毕，调用cyclicBarrier.await()开始等待其它线程
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                //当指定的线程数全都调用了cyclicBarrier.await()方法时，所有线程才开始继续同时执行
                System.out.println(tN + " starts running");
            }).start();
        }
    }

    //子线程完成某件任务后，把得到的结果回传给主线程
    //Runnable接口的run方法没有返回结果，Callable接口能返回泛型V结果
    private static void doTaskWithResultInWorker() {
        Callable<Integer> callable = () -> {
                    System.out.println("Task starts");
                    Thread.sleep(1000);
                    int result = 0;
                    for (int i = 0; i <= 100; i++) {
                        result += i;
                    }
                    System.out.println("Task finished and return result");
                    return result;
                };

        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        try{
            System.out.println("Before futureTask.get()");
            System.out.println("Result:"+futureTask.get());//当主线程调用future.get()方法时阻塞主线程
            System.out.println("After futureTask.get()");
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch(ExecutionException e){
            e.printStackTrace();
        }

    }

    private static void printName(String name) {
        int i = 0;
        while (i++ < 3) {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(name + "print:" + i);
        }
    }


}
